home *** CD-ROM | disk | FTP | other *** search
- COMMENT |
- STUFFKB3.ASM By Richard Kanarek- Compuserve ID 72371,111
- GENIE Address: R.KANAREK
- Overview:
- +Description of file.
- +Notes on the Keyboard Buffer.
- +Sample Assembly Language program which stuffs the phrase
- "BUY BONDS" into your keyboard buffer. May be easily adapted
- for use with Turbo C (tm- Borland Int. Inc.) by changing
- a few lines (all of which are marked).
- +Sample Turbo C program which calls the assembler routine
- and uses it to stuff "RLK" into the buffer.
-
- +Description of file.
- ---------------------
- This file contains information on the operation of the keyboard
- buffer in IBM & Zenith personal computers as well as sample procedure
- (in Assembler) that can be called from a Turbo C (tm) program. This
- file was intended to be compiled using TASM but since only TASM's
- MASM mode is used, compilation using Microsoft's (tm) assembler
- should not be difficult.
-
- Unlike most programs, whose purpose is only to be executed, the
- purpose of this program is to explain the operation of the Keyboard
- buffer. This file is meant to help those who might wish to "stuff"
- or otherwise modify the keyboard buffer on any IBM computer. Some
- reasons why you might want to fiddle with the keyboard buffer:
- - Call another program while exiting an already running program
- without tying up ANY memory or interfering with the running program
- in any way.
- - Change the keyboard buffer size to allow more or fewer keystrokes
- to be stored.
- - Write a TSR that can demonstrate other programs by simulating keystrokes,
- without having or needing access to the other programs source code.
-
- Things to consider:
- - EXTENSIVELY TEST ANY PROGRAM THAT STUFFS THE KEYBOARD BUFFER!!! Very slight
- mistakes can create impressively buggy software! Make sure that the routines
- do not leave any lasting effects (i.e. try running other programs after
- running any program that stuffs the buffer). Assume that any software
- that will stuff the keyboard will crash on your first effort writing it-
- IN HEAVEN'S NAME SAVE TO FLOPPY DISK (THEN REMOVE THE DISK FROM YOUR DRIVE)
- YOUR WORK IN PROGRESS BEFORE TRYING YOU NEW PROGRAM! HARD DISK USERS- DEBUG
- AT YOUR OWN RISK! The memory area near the key board buffer is used for
- important purposes by your computer. Accidentally writing to them will cause
- the computer to operate unreliably- though not necessarily so unreliably
- that you will notice it immediately! For example: while developing the
- routines below, there was a bug present which would cause the procedure
- to (apparently) not write to the buffer but it did not seem to cause any
- other problems (TASM, TLINK, & Turbo C still worked fine). When I tried
- starting Turbo Debugger, my computer would lock up! Once again: Test, Test,
- Test!!!
-
- - These routines have only been tried on Heath/Zenith XT similar
- computer (not 100% clone, but close). Verify on you own if the
- concepts described below will work else where!
-
- - If you are sure that your computers BIOS supports int 16h fun 05h you can
- use it to safely write data to the keyboard buffer:
- Calling Registers: (From "System BIOS for IBM PC/XT/AT Computers &
- ax=05h Compatibles", Phoenix Tech. Reference)
- ch=scan code
- cl=ascii character
- Return Registers:
- al= 00h=No Error, 01h= Buffer Full.
- This BIOS int. is only supported on latter xt and on at computers. To
- determine if the computer running a program supports INT 16h fun.'s 5h,10h,
- 12h...
- (quoting Phoenix book...)
- a) Use Fun. 05h to write FFFFh to the keyboard buffer. If AL returns 00h
- then fun. 05h is supported.
- b) Read the keyboard using fun. 10 as many times as there are words in
- the keyboard buffer (the book recommends 15). If FFFFh is returned fun.
- 10h-12h are supported.
- - This program was NOT extensively tested. USE AT YOUR OWN RISK! Please
- report any problems or useful information on keyboard stuffing to the
- author so that I may keep these notes as complete as possible.
- - Note: IBM AT & PS/2 Keyboards generate different codes than do the XT
- keyboards this program was written for. I don't believe that these
- differences will affect this program in any way but this has not been
- tested yet. You may wish to check that different keyboards work equally
- well before using these routines in any important programs.
- - Note: This program was compiled (using Turbo Assembler & TLINK) with
- case sensitivity & all debugging options on. Recompiling should not produce
- any error messages.
- - IMPORTANT: Needless to say (but that won't stop me!)...
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- +The information and routines below may be used without charge so long as +
- +the author is not held, in any way, labial for the soundness of the routines+
- +or accuracy of the information. Any source code included in this file may +
- +be considered "Public Domain". RLK Jan 9 1990 +
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-
- +Notes on the Keyboard Buffer.
- ------------------------------
- The keyboard buffer is a circular buffer.
- The main components of the keyboard buffer are:
- 1) A variable which keeps track of where the scan code for the oldest (first)
- unread key is located. This variable is often called the Head.
- 2) A variable which keeps track of where the scan code for the most recently
- press key is located. This variable is often called the Tail.
- 3) A variable which contains the offset for the beginning of the keyboard
- buffer's memory area. This variable is often called the Start.
- 4) A variable which contains the offset for the end of the keyboard
- buffer's memory area. This variable is often called the End.
-
- As keys are pressed, the scan code (WORD) is placed in a memory location
- pointed to by Tail. The tail pointer is then incremented by two (2 bytes=
- one word) unless the Tail pointer is 2 memory locations (bytes) before
- the Head pointer in which case the keyboard buffer is now full.
- If incrementing the Tail pointer makes it greater than the value of End,
- Tail is set to equal Start.
- When a BIOS interrupt reads a scan code from the keyboard buffer, it reads
- the scan code pointed to by Head & then increments the Head pointer by
- two. (Note: No key is read from the buffer if the buffer is empty, i.e.
- if Head=Tail.)
- If incrementing the Head pointer makes it greater than the value of End,
- Head is set to equal Start.
-
-
- ==IBM========================================================================
- (Heath/ZDS computer programmers, see next section).
- Note Worthy BIOS/RAM Locations concerning the Keyboard Buffer:
- Note Segment = 040h
- Offset Data type Description
- 80h Word Address of the start of the keyboard buffer, i.e.
- 40h:[40h:80h] = the location of the first word of
- the keyboard buffer.
- 82h Word Address of the end of the keyboard buffer.
-
- 1Eh-2Eh -------- 16 bytes of the default keyboard buffer area.
- Note: By changing the start and end addresses
- of the keyboard buffer (while making sure that
- the RAM you point the buffer to isn't being/going
- to be used by anything else!) you can greatly
- increase/decrease the buffer size. (For example,the
- reference manual for my Heath Zenith 148 computer has
- a small program in it which changes the buffer to 4000 bytes.)
-
- 1Ah Word Pointer to the first word to be read from the
- keyboard buffer- called "Head" by expert keyboard
- stuffers like you and I! Note: since the keyboard
- buffer is circular in nature, the first word of the
- keyboard buffer is not necessarily the first word
- to be read (but the word pointed to by this offset
- IS!).
-
- 1Ch Word Pointer to the end of the buffer (NOT to be confused
- with the end of the buffer AREA!) where the next
- keypress scan code is to be written- expert keyboard
- stuffers like you and I call it the "Tail".
-
- ==Zenith=====================================================================
- Zenith Computer keyboard buffers are arranged in a manor very similar to
- IBM computers except as follows:
- Address Data type Description
- F000:00C8 Word Segment Address of Keyboard Buffer area.
- F000:00CA Word Offset address of Start of keyboard buffer- i.e.
- keyboard buffer mem. starts @ [F000:00C8]:[F000:00CA]
- F000:00CC Word Offset address of End of keyboard buffer- i.e.
- keyboard buffer memory Ends at [F000:00C8]:[F000:00CC]
- Notice that Zenith BIOS makes changing the size of the keyboard buffer very
- easy- just point [F000:00C8]:[F000:00CA] to the start of an unused area of
- memory and [F000:00C8]:[F000:00CC] to the end of the block of memory.
- By default, Zenith keyboard buffers occupy the same memory area as IBM
- computers.
-
- ==GENERAL====================================================================
-
- Note: Each buffer WORD contains:
- LSB=ASCII Value of key (zero if function key)
- MSB= Scan Code
- Where: [WORD]=[MSB][LSB]
- ^ ^
- Byte Byte
- KEEP IN MIND THAT WORDS ARE STORED IN MEMORY WITH THE LEAST SIGNIFICANT BYTE
- FIRST AND THE MOST SIGNIFICANT BYTE LAST, SO A SCAN CODE IS STORED
- IN MEMORY IN A MANOR OPPOSITE TO THAT WHICH WAS JUST DESCRIBED.
-
- Useful (?) Observations on the operation of the keyboard buffer:
- (Observations made on a Heath Zenith 148 [xt- `99%' compatible]
- computer.)
- - When keyboard buffer is empty head=tail.
- - Cntrl/Alt/Break Clears buffer (sets head=tail).
- - Buffer holds 15 Key presses (default) max.
- - Buffer "start" & "end" addresses are inclusive.
- - Buffer full: tail= head-2 (Remember: buffer is circular- if head-2 would
- be less than start, wrap around buffer)
-
- Note: The below examples assume that the keyboard buffer has been setup
- in the way that a IBM computer would by default. It has been left up to
- you to determine, if necessary, whether this default condition still exists.
-
- Bibliography:
- Technical Reference manual for Heath/Zenith 148 Computer.
- "System BIOS for IBM PC/XT/AT Computers& Compatibles" by Pheniox Technologies
-
- +Sample Assembly Language program:
- ----------------------------------
-
- ---Actual Sample Program Starts Below.
-
- ;As supplied, the code below will clear the keyboard buffer & then stuff the
- ; keyboard with a sample phrase. To perform a truly useful task, you will have
- ; to include the below routines is another program. If you wish, you may
- ; easily adapt this file for linking with Turbo C (tm) by simply making
- ; the changes that are clearly noted. If linked with TC you will be
- ; able to stuff the keyboard buffer with any phrase that will fit into
- ; the buffer so long as the phrase uses only characters supported in
- ; the table below. You are, of course, free to change the routine in
- ; any way or use it as a model to create a similar routine in a language
- ; of your choice.
- |
-
- ;Change Model & language as required.
- .model small,C
- ;by setting language to "C" TASM (tm) will automatically insert underbars
- ; under all extrn & public references (darn helpful, don't you think?).
-
- locals ;Permits temporary lables that start with @@
-
- %OUT Compiling STUFFKB3.ASM by Richard Kanarek. Version 1.10
-
- start equ 80h ;Location of Buffer Start offset.
- endd equ 82h ;Location of Buffer End offset.
- head equ 1Ah ;Location of first unread keypress.
- tail equ 1Ch ;Location of last unread keypress.
-
- .stack ;default 1k
- ;Note: Eliminate .stack statement if linking routine with Turbo C. Turbo C
- ; (like other languages) will declare a stack area.
-
-
- .data
- table label BYTE ;The table (below) contains a list of SCAN CODES
- ; which are used with the ASCII codes contained in the ASCIIZ
- ; (0h terminated string) keyboard stuffing string to stuff
- ; the keyboard buffer.
- ;Note: the layout of this array is somewhat difficult to explain or
- ; understand however it is key to the operation of the below procedure.
- ; Please read the following carefully and/or repeatedly.
- ;All entries in the keyboard buffer consist of two bytes (one word).
- ;When viewed as a word, the first byte is the key code - a number
- ; indicating which key was pressed & the second byte indicates the
- ; ASCII code for the key press (0 for function keys). KEEP IN MIND
- ; THAT WORDS ARE STORED IN MEMORY WITH THE LEAST SIGNIFICANT BYTE
- ; FIRST AND THE MOST SIGNIFICANT BYTE LAST, SO A SCAN CODE IS STORED
- ; IN MEMORY IN A MANOR OPPOSITE TO THAT WHICH WAS JUST DESCRIBED.
- ;table_ascii_start is an Equate (#define) which is assigned the
- ; ascii value of the first key code contained in the array `table'.
- ;The array `table' is actually made up exclusively of key codes. The
- ; first key code in the array `table' has the ASCII code of
- ; table_ascii_start. The second key code in the array `table' has the
- ; ASCII code of table_ascii_start + 1.
- ;Note: This table does not support all ascii keys (life is to short
- ; to enter 255 entries into the table). You many feel free to add
- ; entries if you like.
- ;Note: Keys not supported are given the value FFh if their ASCII
- ; code is between table_ascii_start & (table_ascii_start + table_size)
- ; The only significance of the value FFh is that I decided to assign
- ; it to keys I did not enter into the table and that I wrote the below
- ; procedure to check for it.
- ; Other unsupported keys are just ignored in the table (though the
- ; routine below checks if a character in the string to be stuffed
- ; is actually included in the table).
- ;Note: Table entries must be in sequence, from lowest ASCII code to
- ; highest ASCII code.
- table_ascii_start = 0Dh ;ASCII code for the first (lowest) keyboard key
- ; covered by this table (i.e. the following key).
- db 1Ch ;[Return] <-- ASCII code = table_ascii_start
-
- db 12h dup (0FFh) ;I don't think it would be a useful use of
- ; my time to fill in [Cntrl]/[keypress] codes,
- ; do you?
-
- db 39h ;[Space]
-
- db 0Ah dup (0FFh) ; <ditto>
-
- db 33h ;,
- db 0Ch ;-
- db 34h ;.
- db 35h ;/
-
- db 02h ;0
- db 03h ;1
- db 04h ;2
- db 05h ;3
- db 06h ;4
- db 07h ;5
- db 08h ;6
- db 09h ;7
- db 0Ah ;8
- db 0Bh ;9
-
- db 27h ;:
- db 27h ;;
- db 33h ;<
- db 0Dh ;=
- db 34h ;>
- db 35h ;?
-
- db 03h ;@
-
- db 1Eh ;A Notice that I only entered capital letters into
- db 30h ;B the table. Don't call the procedure
- db 2Eh ;C with a ASCIIZ string containing lower case
- db 20h ;D letters unless you enter them in the table.
- db 12h ;E
- db 21h ;F
- db 22h ;G
- db 23h ;H
- db 17h ;I
- db 24h ;J
- db 25h ;K
- db 26h ;L
- db 32h ;M
- db 31h ;N
- db 18h ;O
- db 19h ;P
- db 10h ;Q
- db 13h ;R
- db 1Fh ;S
- db 14h ;T
- db 16h ;U
- db 2Fh ;V
- db 11h ;W
- db 2Dh ;X
- db 15h ;Y
- db 2Ch ;Z
-
- db 1Ah ;[
- db 2Bh ;\
- ;End of table.
- table_size=$-table ;stores size of table in equate table_size.
-
- test_string db "BUY BONDS",0 ;for test only.
- ;Note: Remove test string if "main:" is removed, i.e. when calling the
- ; below routine from another program.
- ;Note: The above string does not contain an ASCII character 0Dh. The effect
- ; is therefore the same as your pressing the [B], [U], [Y], [Space], etc.
- ; keys without pressing the enter key! Adding a ODh value would be the
- ; same as pressing the enter key.
-
-
- .code
-
- ;Note: Eliminate "main:" code as required.
- ;\/ \/ \/ \/ \/ \/ \/ \/ \/
-
- main: ;used for test only.
-
- mov ax,@data ;Initialize Data Segment.
- mov ds,ax ;
-
- mov ax,OFFSET [test_string] ;Note: Don't forget to include a ascii
- ; char. 13d (return) in the string (if needed).
- push ax ;Offset (pointer) to test String is pointed to by
- ; word pushed on stack (even when the routine is called
- ; by another program).
-
- call stuffkybd ;This is the routine that "Stuffs" the keyboard.
-
- pop bx ;Remove the pushed pointer from the stack.
-
- ;return to DOS.
- mov ah,4ch ;sets ah reg for dos interrupt 21h
- int 21h ; function 4ch (Terminate)
-
- ;/\ /\ /\ /\ /\ /\ /\ /\ /\
-
-
- proc stuffkybd
-
- ;Include the following line in the calling Turbo C program:
- ;extern int stuffkybd(char *asciiz_string)
- ;Note: string must be upper case only and use only those characters supported
- ; by the table (above).
-
- ;stuffkybd returns 1 if stuffkybd fails, 0 otherwise.
-
- ;Notice (by examining the table, above) that only CAPITAL letters, numbers,
- ; and a few other keys are currently supported. If you wish to use an
- ; unsupported key, you must add its scan code to the proper position in the
- ; table.
-
- ;Note: In order to work a)DS must point to the segment containing the ASCIIZ
- ; string to stuff & b) a word offset pointer, such that DS:OFFSET = Start
- ; of ASCIIZ must have been pushed on to the stack before calling this
- ; procedure.
-
- public stuffkybd
- arg string:WORD
-
- push es ;Saves some registers. You may need to save other registers
- push si ; or flags depending upon the calling program!
- push di ;
-
- mov ax,40h ;Initializes es register to
- mov es,ax ; BIOS RAM segment.
-
-
-
- ;make keyboard buffer appear full so that no (alphanumeric) keypresses
- ; will interfere with loading.
- mov ax,WORD ptr [es:start] ;Load AX with the start
- ; offset address (seg.=40h)
- ; of the keyboard buffer.
-
- cli ;Disables interrupts (prevents any more writes
- ; to the keyboard buffer).
-
- mov WORD ptr [es:head],ax ;Head now equals Start.
-
- mov ax,WORD ptr [es:endd]
- dec ax ;AX - 1 (same as Head-2 since Head now = Start).
- mov WORD ptr [es:tail],ax ;Buffer now looks full.
-
- sti ;Permits interrupts.
-
-
- ;fill buffer...
-
- ;First, prepare registers:
- mov bx,OFFSET table ;used by xlat
- mov si,[string] ;si-used to point to string
- ; memory locations (offsets)
- mov di,WORD ptr [es:head] ;DI- used to point to keyboard buffer
- ; locations.
-
- ;Second, prepare loop:
- mov cx,WORD ptr [es:endd] ;TASM is actually quite smart enough
- ; to figure out that [es:endd] is pointing to
- ; a WORD- I just like to make sure that we
- ; are both (TASM & I) understanding each other.
- sub cx,WORD ptr [es:start]
- ;cx now contains the max. number of BYTEs to stuff.
- shr cx,1 ;divide by 2
- ;cx now contains the max. number of WORDS to stuff.
-
- @@looptop2:
- mov al,BYTE ptr [DS:si] ;loads al with ascii char
- ; from string.
- cmp al,0 ;Is ascii value =0 (i.e. is char. string terminator)?
- jne @@continue_loop2
- jmp SHORT @@stuffkybd_success
-
- @@continue_loop2:
-
- mov ah,al ;save ascii char. value.
-
- sub al,table_ascii_start ;Adj. ascii value for use with XLAT.
-
- jl @@stuffkybd_fail ;if the ascii value is less than those the
- ; table is setup for, then jump.
-
- cmp al,table_size ;Check that the ascii value is not greater
- ; than those the table was setup for.
- jg @@stuffkybd_fail
-
- xlat ;Shazame! al now contains the scan code for the ascii key.
-
- ;Was the value returned in al by xlat a real value or one of those
- ; phoney FFh's I entered into the table because I was to lazy to
- ; enter all possible values?
-
- cmp al,0FFh
- je @@stuffkybd_fail
-
- xchg al,ah ;puts the word value in the correct order.
-
- mov WORD ptr [es:di],ax ;`stuff' keyboard buffer
-
- inc di ;Point di to next WORD in keyboard buffer.
- inc di ; (two inc's = fast `add di,2')
- inc si ;Point si to next BYTE in keyboard stuff string.
-
- loop @@looptop2 ;Dec CX then jump to @@looptop2 if cx<>0.
-
- @@loop2exit:
- ;If PC reaches this point:
- ; a) The null terminator for the string has not been reached yet.
- ; and
- ; b) The string is bigger than the buffer.
- ; or
- ; b) The string size = the max size of the buffer.
- ;Lets find out which.
-
- mov ax,WORD ptr [es:si]
- cmp ax,0
- je @@stuffkybd_success
-
- @@stuffkybd_fail:
- mov ax,WORD ptr [es:head] ;
- mov WORD ptr [es:tail],ax ;"clears" keyboard buffer.
- mov ax,1 ;stuffkybd returns 1 if stuffkybd fails, 0 otherwise.
- jmp SHORT @@return2caller
- @@stuffkybd_success:
- mov ax,WORD ptr [es:endd] ;Calculate new value for `tail'.
- sal cx,1
- sub ax,cx
- mov WORD ptr [es:tail],ax ;Load new value into tail.
- xor ax,ax ;returns 0
- @@return2caller:
-
- @@pop_n_ret:
- pop di
- pop si
- pop es
- ret
-
- stuffkybd endp
-
-
- end main
- ;Note: Change to just `end' if eliminating "main:" section (i.e. if
- ; calling from another program.
-
-
-
-
-
-
-
- ;A sample Turbo C 2.01 (tm- Borland Int. Inc.) program appears below. Use
- ; your favorite text editor to extract & compile it, if you wish.
-
-
-
- COMMENT |
- A sample Turbo C program you can use after you've made the few changes
- (to this program) noted.
-
-
- /*
- Example on calling stuffkybd. For complete notes see STUFFKYBD?.ASM
-
- Richard Kanarek Compuserve 72371,111 GENIE R.KANAREK
- */
-
-
- #include <stdio.h>
- #include <conio.h>
-
- extern int stuffkybd(char * teststring); /* returns 0 if ok, 1 if
- fail. */
-
- main()
- {
- char *teststring="RLK";
- /*Note: 1) Turbo C automatically adds the
- 0 string terminator. 2) RLK is just printed at the DOS
- prompt (when SAMPLE.EXE is run from DOS). If you replace
- RLK with a command you will have to add a 0Dh character
- (for a CR- \x0d).
- Idea: You might wish to change STUFFKB?.ASM so that
- rather than just stuffing the string into the keyboard
- it also fills the remaining space with spaces (20h). This
- would prevent the user from appending any keystrokes to
- the text you loaded into the buffer. */
-
- int a;
-
- clrscr(); /*Clears the monitor screen. */
- a=stuffkybd(teststring);
- printf("Return code: %d \n",a);
- }
-
- |
-